﻿using DevExpress.Data;
using DevExpress.Export;
using DevExpress.Utils;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.BandedGrid;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraPrinting;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace DevTeam
{
    public static class GridViewExtensions
    {
        public delegate void BindingHandler(GridView gridView, BindingSource bs);
        public static event BindingHandler Binding;

        public static GridManager GetManager(this GridView gridView)
        {
            return GridManager.GetManager(gridView);
        }

        public static DataSet Dataset(this GridView gridView)
        {
            GridManager gm = gridView.GetManager();
            return gm.DataSet;
        }

        public static DataTable DataTable(this GridView gridView)
        {
            GridManager gm = gridView.GetManager();
            return gm.DataTable;
        }

        #region Extensions

        private static bool CheckInvalidColumns(this List<string> invalidColumns)
        {
            StackTrace st = new StackTrace();
            string senderMethod = st.GetFrame(1).GetMethod().Name;

            if (invalidColumns.Count > 0)
            {
                KeyNotFoundException aex = new KeyNotFoundException("IGNORABLE-" + senderMethod + " hata! Bulunmayan sütunlar: " + string.Join(",", invalidColumns), new Exception(st.ToString()));

                LogManager.LogToDB(aex);
                //LogManager.Notify(aex);
                return false;
            }
            return true;
        }

        #region Formatting
        public static void FormatAsDateTime(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName];

                if (col != null)
                {
                    col.DisplayFormat.FormatType = FormatType.DateTime;
                    col.DisplayFormat.FormatString = "dd.MM.yyyy HH:mm:ss";
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void FormatAsDate(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName];

                if (col != null)
                {
                    col.DisplayFormat.FormatType = FormatType.DateTime;
                    col.DisplayFormat.FormatString = "dd.MM.yyyy";
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void FormatAsNumber(this GridView gridView, int decimalPoints, params string[] columnNames)
        {
            gridView.BeginDataUpdate();
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName];

                if (col != null)
                {
                    col.DisplayFormat.FormatType = FormatType.Numeric;
                    string format = "#,##0.";
                    for (int i = 0; i < decimalPoints; i++)
                        format += "0";

                    if (format.EndsWith("."))
                        format = format.Substring(0, format.Length - 1);
                    col.DisplayFormat.FormatString = format + ";-" + format + "; ";

                    col.FilterMode = ColumnFilterMode.Value;
                    col.ColumnEdit = RepositoryManager.MaskedNumeric(decimalPoints != 1 ? decimalPoints : 2);
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
            gridView.EndDataUpdate();
        }

        private static void FormatAsPercentageBase(this GridView gridView, int decimalPoints, bool ShowAsProgressBar, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName];

                if (col != null)
                {
                    if (ShowAsProgressBar)
                    {
                        RepositoryItemProgressBar pb = new RepositoryItemProgressBar();
                        pb.ShowTitle = true;
                        pb.PercentView = true;
                        pb.Maximum = 100;
                        col.ColumnEdit = pb;
                        //pb.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
                        //pb.DisplayFormat.FormatString = "P2";
                    }
                    else
                    {
                        col.DisplayFormat.FormatType = FormatType.Numeric; ;
                        col.DisplayFormat.FormatString = "P" + decimalPoints.ToString();
                        //col.FilterMode = DevExpress.XtraGrid.ColumnFilterMode.Value;
                    }
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void FormatAsPercentage(this GridView gridView, params string[] columnNames)
        {
            gridView.FormatAsPercentageBase(-1, true, columnNames);
        }

        public static void FormatAsPercentage(this GridView gridView, int DecimalPoints, params string[] columnNames)
        {
            gridView.FormatAsPercentageBase(DecimalPoints, false, columnNames);
        }
        #endregion

        public static void SetViewCaption(this GridView gridView, string Caption)
        {
            gridView.OptionsView.ShowViewCaption = true;
            gridView.ViewCaption = Caption;
        }

        public static void ClearColumnEdit(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName];
                if (col != null)
                {
                    col.ColumnEdit = null;
                    col.Caption = null;
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void Freeze(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (var colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName.Replace("ProductId", "PRO")];
                if (col != null)
                    col.Fixed = FixedStyle.Left;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        /// <summary>
        /// Sütun başlıklarını düzenler.
        /// </summary>
        /// <param name="gridView"></param>
        /// <param name="pairs">Sütunİsmi:Başlık, Sütunİsmi:Başlık , ...</param>
        public static void SetCaptions(this GridView gridView, params string[] pairs)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string pair in pairs)
            {
                string[] vals = pair.Split(':');
                string colName = vals[0].Trim().Replace("ProductId", "PRO");
                string caption = vals[1].Trim();
                GridColumn col = gridView.Columns[colName];
                if (col != null)
                {
                    col.Caption = caption;
                    if (caption == "#")
                        col.ToolTip = colName;
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void SetToolTip(this GridView gridView, params string[] pairs)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string pair in pairs)
            {
                string[] vals = pair.Split(':');
                string colName = vals[0].Trim().Replace("ProductId", "PRO");
                string toolTip = vals[1].Trim();
                GridColumn col = gridView.Columns[colName];
                if (col != null)
                    col.ToolTip = toolTip;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void MakeColumnVisible(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName.Replace("ProductId", "PRO")];
                if (col != null)
                    col.Visible = true;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void MakeRowSelectable(this GridView gridView)
        {
            gridView.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect;  //CheckBoxRowSelect
            gridView.OptionsSelection.MultiSelect = true;
        }

        public static void MakeCompulsory(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();
            foreach (string colName in columnNames)
            {
                string columnName = colName.Replace("ProductId", "PRO");

                GridColumn col = gridView.Columns[columnName];
                if (col != null)
                    col.AppearanceCell.BackColor = Color.FromName(Session.Settings.ZorunluAlanRengi);  // System.Drawing.Color.Gold;
                else
                    invalidColumns.Add(columnName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void AddSummary(this GridView gridView, params string[] columnNames)
        {
            gridView.BeginDataUpdate();
            List<string> scanColumns = new List<string>() { "Scan", "Photo", "ScanA", "ScA" };
            List<string> invalidColumns = new List<string>();

            gridView.OptionsView.ShowFooter = true;
            if (gridView.VisibleColumns.Count > 0)
            {
                GridColumn col = gridView.VisibleColumns[0];
                if (scanColumns.Contains(col.FieldName))
                    col = gridView.VisibleColumns[1];

                col.SummaryItem.SummaryType = SummaryItemType.Count;
                col.SummaryItem.DisplayFormat = "{0:#,##0} kayıt";
            }

            foreach (string colName in columnNames)
            {
                string columnName = colName.Replace("ProductId", "PRO");
                GridColumn col = gridView.Columns[colName];

                if (col != null)
                {
                    GridColumn gc = gridView.Columns[colName];

                    gc.SummaryItem.FieldName = colName;
                    gc.SummaryItem.SummaryType = SummaryItemType.Sum;
                    gc.SummaryItem.DisplayFormat = "{0:#,##0.#}";
                }
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
            gridView.EndDataUpdate();

        }

        public static void MakeColumnInvisible(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName.Replace("ProductId", "PRO")];

                if (col != null)
                    col.Visible = false;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void SetFilterTypeToCheckedList(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                string columnName = colName.Replace("ProductId", "PRO");
                GridColumn col = gridView.Columns[columnName];

                if (col != null)
                {
                    col.OptionsFilter.FilterPopupMode = FilterPopupMode.CheckedList;
                    //col.FilterMode = DevExpress.XtraGrid.ColumnFilterMode.Value;
                    //col.OptionsFilter.ImmediateUpdateAutoFilter = true;
                    //col.OptionsFilter.ImmediateUpdatePopupDateFilterOnCheck = DefaultBoolean.True;
                    //col.OptionsFilter.ImmediateUpdatePopupDateFilterOnDateChange = DefaultBoolean.True;
                }
                else
                    invalidColumns.Add(columnName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void MakeColumnsReadOnly(this GridView gridView, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string colName in columnNames)
            {
                GridColumn col = gridView.Columns[colName.Replace("ProductId", "PRO")];
                if (col != null)
                    col.OptionsColumn.AllowEdit = false;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        private static void SetEditable(this GridView gridView, bool MakeEditable, params string[] ExceptTheseColumns)
        {
            List<string> invalidColumns = new List<string>();

            foreach (GridColumn col in gridView.Columns)
                col.OptionsColumn.AllowEdit = MakeEditable;

            foreach (string colName in ExceptTheseColumns)
            {
                GridColumn col;
                if (colName == "ProductId")
                {
                    col = gridView.Columns["ProductId"];

                    if (col != null)
                        col.OptionsColumn.AllowEdit = !MakeEditable;
                    else
                        invalidColumns.Add(colName);
                }

                col = gridView.Columns[colName.Replace("ProductId", "PRO")];

                if (col != null)
                    col.OptionsColumn.AllowEdit = !MakeEditable;
                else
                    invalidColumns.Add(colName);
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void MakeEditable(this GridView gridView, params string[] ExceptTheseColumns)
        {
            gridView.SetEditable(true, ExceptTheseColumns);
        }

        public static void MakeReadOnly(this GridView gridView, params string[] ExceptTheseColumns)
        {
            gridView.SetEditable(false, ExceptTheseColumns);
        }

        public static void EndEditing(this GridView gridView)
        {
            gridView.CloseEditor();
            gridView.UpdateCurrentRow();
        }

        public static void SetAlternateRowStyle(this GridView gridView, bool Status)
        {
            gridView.OptionsView.EnableAppearanceEvenRow = Status;
            gridView.OptionsView.EnableAppearanceOddRow = false;
        }

        public static void ChangeExpression(this GridView gridView, string columnName, string expression, int TableIndex = 0)
        {
            List<string> invalidColumns = new List<string>();

            if (expression.Contains("{FK}"))
            {
                string FKName = string.Empty;

                if (expression.ToLower().Contains("child"))
                    FKName = gridView.DataTable().ChildRelations[TableIndex].RelationName;
                if (expression.ToLower().Contains("parent"))
                    FKName = gridView.DataTable().ParentRelations[TableIndex].RelationName;

                expression = expression.Replace("{FK}", FKName);
            }

            DataTable dataSource = gridView.DataTable();

            if (dataSource.Columns[columnName] != null && gridView.Columns[columnName] != null)
            {
                dataSource.Columns[columnName].Expression = expression;
                gridView.Columns[columnName].UnboundExpression = expression;
            }
            else
                invalidColumns.Add(columnName);

            invalidColumns.CheckInvalidColumns();
        }

        #region YanYanaGetir
        public static void YanYanaGetir(this GridView gridView, params string[] pairs)
        {
            List<string> invalidColumns = new List<string>();

            foreach (string pair in pairs)
            {
                string[] vals = pair.Split(':');
                string colName1 = vals[0].Trim().Replace("ProductId", "PRO");
                string colName2 = vals[1].Trim();

                GridColumn col1 = gridView.Columns[colName1];
                GridColumn col2 = gridView.Columns[colName2];

                if (col1 == null)
                    invalidColumns.Add(colName1);
                else if (col2 == null)
                    invalidColumns.Add(colName2);
                else
                    col1.VisibleIndex = col2.VisibleIndex;
            }

            invalidColumns.CheckInvalidColumns();
        }

        private static void YanYanaGetirYonlu(this GridView gridView, string BaseColumn, bool Soluna, params string[] columnNames)
        {
            List<string> invalidColumns = new List<string>();

            bool isBanded = gridView.GetType() == typeof(BandedGridView);
            GridColumn colBase = gridView.Columns[BaseColumn];
            if (colBase == null)
                invalidColumns.Add(BaseColumn);
            else
            {
                int i = 0;

                if (Soluna)
                {
                    if (isBanded)
                        i = (colBase as BandedGridColumn).ColVIndex - 1;
                    else
                        i = colBase.VisibleIndex;
                }
                else
                {
                    Array.Reverse(columnNames);

                    if (isBanded)
                        i = (colBase as BandedGridColumn).ColVIndex + 1;
                    else
                        i = colBase.VisibleIndex + 1;
                }

                foreach (string colName in columnNames)
                {
                    GridColumn col = gridView.Columns[colName.Replace("ProductId", "PRO")];

                    if (col != null)
                        col.VisibleIndex = i;
                    else
                        invalidColumns.Add(colName);
                }
            }

            invalidColumns.CheckInvalidColumns();
        }

        public static void YanYanaGetirSoluna(this GridView gridView, string BaseColumn, params string[] columnNames)
        {
            gridView.YanYanaGetirYonlu(BaseColumn, true, columnNames);
        }

        public static void YanYanaGetirSagina(this GridView gridView, string BaseColumn, params string[] columnNames)
        {
            gridView.YanYanaGetirYonlu(BaseColumn, false, columnNames);
        }
        #endregion

        /// <summary>
        /// Seçili (yoksa focused) satırlarda, belirtilen sütundaki değerleri virgül ile birleştirip döndürür.
        /// </summary>
        /// <param name="gridView"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static string GetSelectedValues(this GridView gridView, string columnName)
        {
            List<string> vals = new List<string>();
            if (gridView.Columns[columnName] == null)
                throw new KeyNotFoundException(columnName + " sütunu yok!");
            else
            {
                foreach (int rowHandle in gridView.GetSelectedRows())
                    if (rowHandle > -1)
                        vals.Add(gridView.GetRowCellValue(rowHandle, columnName).ToString());

                if (vals.Count == 0
                    && GridControl.NewItemRowHandle != gridView.FocusedRowHandle
                    && GridControl.AutoFilterRowHandle != gridView.FocusedRowHandle
                    )
                    vals.Add(gridView.GetFocusedRowCellValue(columnName).ToString());

                return string.Join(",", vals);
            }
        }

        public static void DisableRowDelete(this GridView gridView)
        {
            GridManager gm = gridView.GetManager();
            gm.RowDeleteDisabled = true;
        }

        public static void EnableRowDelete(this GridView gridView)
        {
            GridManager gm = gridView.GetManager();
            gm.RowDeleteDisabled = false;
        }



        public static void EnableRowSelection(this GridView gridView)
        {
            GridManager gm = gridView.GetManager();

            gridView.AddColumn("Seç", typeof(bool));
            DataTable dt = gridView.DataTable();

            foreach (DataRow dr in dt.Rows)
                dr["Seç"] = false;

            dt.AcceptChanges();

            gridView.Columns["Seç"].ColumnEdit = null;
            gridView.Columns["Seç"].VisibleIndex = 0;
            gridView.Columns["Seç"].Width = 40;
            gridView.Columns["Seç"].OptionsColumn.AllowEdit = false;
            //gridView.SetAlternateRowStyle(false);

            gridView.RowCellClick += gridView_RowCellClick;
            gridView.CustomDrawCell += gridView_CustomDrawCell;
            gridView.RowStyle += gridView_RowStyle;

            gm.RowSelectionEnabled = true;
        }

        static void gridView_RowStyle(object sender, RowStyleEventArgs e)
        {
            if (e.RowHandle > -1)
            {
                GridView gvSender = sender as GridView;
                object val = gvSender.GetRowCellValue(e.RowHandle, "Seç");

                if (val.ToBool())
                {
                    e.Appearance.BackColor = Color.AliceBlue;
                    //e.Appearance.FontStyleDelta = FontStyle.Bold;
                }
                else
                {
                }
            }
        }

        static void gridView_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
        {
            //if (e.RowHandle > -1)
            {
                GridView gvSender = sender as GridView;
                if (e.Column.FieldName == "Seç")
                {
                    object val = e.CellValue;
                    if (val.ToBool())
                    {
                        Font font = new Font(gvSender.Appearance.FocusedCell.Font, FontStyle.Bold);
                        e.Graphics.DrawString("x", font, Brushes.Black, e.Bounds);
                    }
                    else
                    {
                    }

                    e.Handled = true;
                }
            }
        }

        static void gridView_RowCellClick(object sender, RowCellClickEventArgs e)
        {
            if (e.RowHandle > -1)
            {
                GridView gvSender = sender as GridView;
                if (e.Column.FieldName == "Seç")
                {
                    object val = e.CellValue;
                    gvSender.SetRowCellValue(e.RowHandle, e.Column, !val.ToBool());

                    gvSender.EndEditing();
                }
            }
        }



        public static void EnableNewRow(this GridView gridView, NewItemRowPosition Position = NewItemRowPosition.Bottom)
        {
            gridView.OptionsView.NewItemRowPosition = Position;
        }


        public static void ShowOnlyNonblankColumns(this GridView gridView, bool status = true)
        {
            GridManager gm = GridManager.GetManager(gridView);
            gm.ShowOnlyNonblankColumns = status;
        }
        #endregion

        #region Export
        public static void Export(this GridView GridView, string extension, string fileName = "")
        {
            //bool ESP = false;
            ExportSettings.DefaultExportType = DevExpress.Export.ExportType.WYSIWYG;
            foreach (DevExpress.XtraGrid.Columns.GridColumn col in GridView.Columns)
            {
                col.MinWidth = GridView.CalcColumnBestWidth(col);
                //ESP |= col.FieldName.Contains("ESP");
            }

            switch (extension.ToLower())
            {
                case "pdf":
                    if (fileName == string.Empty)
                        fileName = Dialogs.SaveFile("PDF Document", "PDF Dosyaları|*.pdf");

                    if (fileName != string.Empty)
                        GridView.ExportToPdf(fileName);
                    break;

                case "rtf":
                    if (fileName == string.Empty)
                        fileName = Dialogs.SaveFile("RTF Document", "RTF Dosyaları|*.rtf");

                    if (fileName != string.Empty)
                        GridView.ExportToRtf(fileName);
                    break;

                case "xlsx":
                    if (fileName == string.Empty)
                        fileName = Dialogs.SaveFile("Excel Document", "Excel Dosyaları|*.xlsx");

                    if (fileName != string.Empty)
                    {
                        XlsxExportOptions opt = new XlsxExportOptions();
                        //opt.TextExportMode = ESP ? TextExportMode.Text : TextExportMode.Value;
                        opt.TextExportMode = TextExportMode.Value;

                        //opt.RawDataMode = false;
                        //opt.ExportMode = XlsxExportMode.SingleFile;
                        //opt.ExportType = DevExpress.Export.ExportType.DataAware;

                        bool org = GridView.OptionsView.AllowCellMerge;
                        GridView.OptionsView.AllowCellMerge = false;

                        foreach (GridColumn gc in GridView.Columns)
                            if (gc.ColumnEdit != null)
                                switch (gc.ColumnEdit.GetType().ToString())
                                {
                                    case "RepositoryItemLookUpEdit":
                                    case "RepositoryItemGridLookUpEdit":
                                    case "RepositoryItemTimeSpanEdit":
                                        ((RepositoryItem)gc.ColumnEdit).ExportMode = ExportMode.DisplayText;
                                        break;
                                }

                        GridView.OptionsView.ColumnAutoWidth = false;
                        GridView.OptionsPrint.AutoWidth = false;
                        GridView.BestFitColumns();

                        GridView.ExportToXlsx(fileName, opt);
                        GridView.OptionsView.AllowCellMerge = org;
                    }
                    break;
            }

            if (fileName != string.Empty)
            {
                Session.DataManager.ExecuteNonQuery("InsLogExport", GridView.GridControl.FindForm().Name, GridView.Name, extension.ToLower(), Session.CurrentUser.UserId);

                if (XtraMessageBox.Show("Bu dosyayı açmak istiyor musunuz?", "Gönder...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    FileManager.RunFile(fileName);
            }
        }

        public static void ExportToExcel(this GridView gridView)
        {
            gridView.Export("xlsx");
        }

        public static void ExportToRTF(this GridView gridView)
        {
            gridView.Export("rtf");
        }

        public static void ExportToPDF(this GridView gridView)
        {
            gridView.Export("pdf");
        }
        #endregion

        #region Init & AddDetailGrid

        public static BindingSource Init(this GridView gridView, DataTable dataTable)
        {
            DataSet dataset = dataTable.DataSet;
            if (dataset == null)
            {
                dataset = new DataSet();
                dataset.Tables.Add(dataTable);
            }

            GridManager gm = gridView.GetManager();
            gm.DataSet = dataset;
            gm.DataTable = dataTable;
            gm.BindingSource = new BindingSource(gm.DataSet, gm.DataTable.TableName);

            if (Binding != null)
                Binding(gridView, gm.BindingSource);

            return gm.BindingSource;
        }

        public static BindingSource Init(this GridView gridView, string SPName, params object[] SPParams)
        {
            DataSet dsData = Session.DataManager.ExecuteDataSet(SPName, SPParams);
            GridManager gm = gridView.GetManager();
            gm.DetailGrids.Clear();
            gm.DataSet = dsData;
            gm.DataTable = dsData.Tables[0];
            gm.BindingSource = new BindingSource(gm.DataSet, gm.DataTable.TableName);

            if (Binding != null)
                Binding(gridView, gm.BindingSource);

            return gm.BindingSource;
        }

        /// <summary>
        /// Master grid'e detail grid eklemek için kullanılır.
        /// </summary>
        /// <param name="gvMaster"></param>
        /// <param name="gvDetail"></param>
        /// <param name="commaSeperatedKeyColumns"></param>
        /// <param name="DetailTableIndex">Detail olarak gösterilecek tablonun dataset içindeki indeksi. Eğer belirtilmezse master tablodan DetailGrid sayısı kadar sonraki tablo detay olarak belirlenir.</param>
        /// <returns></returns>
        public static BindingSource AddDetailGrid(this GridView gvMaster, GridView gvDetail, string commaSeperatedKeyColumns, int DetailTableIndex = -1)
        {
            gvMaster.BeginUpdate();
            gvDetail.BeginUpdate();

            GridManager gmMaster = gvMaster.GetManager();

            DataSet dsMaster = gmMaster.DataSet;
            DataTable dtMaster = gmMaster.DataTable;
            int indexMaster = dsMaster.Tables.IndexOf(dtMaster);

            GridManager gmDetail = gvDetail.GetManager();
            gmDetail.DataSet = dsMaster;

            if (DetailTableIndex == -1)
                gmDetail.DataTable = dsMaster.Tables[indexMaster + gmMaster.DetailGrids.Count + 1];
            else
                gmDetail.DataTable = dsMaster.Tables[DetailTableIndex];

            string[] colNames = commaSeperatedKeyColumns.Split(',');

            List<DataColumn> dcPKs = new List<DataColumn>();
            List<DataColumn> dcFKs = new List<DataColumn>();

            foreach (string colName in colNames)
            {
                string col = colName.Trim();
                dcPKs.Add(dtMaster.Columns[col]);
                dcFKs.Add(gmDetail.DataTable.Columns[col]);
            }

            string relationName = string.Format("FK_{0}_{1}_{2}_{3}", gvMaster.Name, gvDetail.Name, commaSeperatedKeyColumns.Replace(',', '_').Replace(" ", ""), gmMaster.DetailGrids.Count + 1);
            DataRelation dr = new DataRelation(relationName, dcPKs.ToArray(), dcFKs.ToArray());

            dtMaster.ChildRelations.Add(dr);

            gmDetail.BindingSource = new BindingSource(gmMaster.BindingSource, relationName);

            if (Binding != null)
                Binding(gvDetail, gmDetail.BindingSource);


            foreach (string colName in colNames)
            {
                string columnName = colName.Trim();
                gvDetail.Columns[columnName].Visible = false;

                if (columnName == "ProductId")
                {
                    if (gvDetail.Columns["Scan"] != null)
                        gvDetail.Columns["Scan"].Visible = false;

                    if (gvDetail.Columns["PRO"] != null)
                        gvDetail.Columns["PRO"].Visible = false;
                }
            }

            gmMaster.DetailGrids.Add(gvDetail);
            if (!commaSeperatedKeyColumns.Contains(",")) //PK set edilebilmesi için tek bir sütun olmalı
            {
                gmMaster.PK = commaSeperatedKeyColumns;
                //gvMaster.AddAutoIncrementalColumn(commaSeperatedKeyColumns);
            }

            gvMaster.EndUpdate();
            gvDetail.EndUpdate();

            return gmDetail.BindingSource;
        }

        #endregion

        #region RefreshDataSource
        public static void RefreshDataSource(this GridView gridView, DataTable dt, bool ClearOldData = true)
        {
            gridView.BeginUpdate();
            DataSet dsRoot = gridView.Dataset();
            if (ClearOldData)
                dsRoot.Tables[dt.TableName].Clear();

            dsRoot.Tables[dt.TableName].Merge(dt);
            gridView.EndUpdate();
        }

        public static void RefreshDataSource(this GridView gridView, DataSet d, bool ClearOldData = true)
        {
            gridView.BeginUpdate();
            DataSet dsRoot = gridView.Dataset();
            if (ClearOldData)
                dsRoot.Clear();

            dsRoot.Merge(d);
            gridView.EndUpdate();
        }

        public static void RefreshDataSource(this GridView gridView, bool ClearOldData, string SPName, params object[] SPParams)
        {
            DataSet dsNew = Session.DataManager.ExecuteDataSet(SPName, SPParams);
            RefreshDataSource(gridView, dsNew, ClearOldData);
        }

        public static void RefreshDataSource(this GridView gridView, string SPName, params object[] SPParams)
        {
            RefreshDataSource(gridView, true, SPName, SPParams);
        }
        #endregion

        #region AddColumn
        private static void AddColumn(this GridView gridView, string name, string expression = null)
        {
            GridColumn col = new GridColumn();
            if (gridView is BandedGridView)
                col = new BandedGridColumn();

            col.FieldName = col.Caption = col.Name = name;
            if (expression != null)
            {
                col.UnboundType = UnboundColumnType.Bound;
                col.UnboundExpression = expression;
            }
            col.Visible = true;
            gridView.Columns.Add(col);
        }

        public static void AddColumn(this GridView gridView, string name, Type type)
        {
            DataTable dataSource = gridView.DataTable();
            dataSource.Columns.Add(name, type);
            gridView.AddColumn(name);
        }

        public static void AddColumn(this GridView gridView, string name, Type type, string expression, int RelationIndex = 0)
        {
            DataTable dataSource = gridView.DataTable();

            if (expression.Contains("{FK}"))
            {
                string FKName = string.Empty;

                if (expression.ToLower().Contains("child"))
                    FKName = dataSource.ChildRelations[RelationIndex].RelationName;
                if (expression.ToLower().Contains("parent"))
                    FKName = dataSource.ParentRelations[RelationIndex].RelationName;

                expression = expression.Replace("{FK}", FKName);
            }


            dataSource.Columns.Add(name, type);

            if (expression != string.Empty)
                dataSource.Columns[name].Expression = expression;

            gridView.AddColumn(name, expression);

        }

        public static void AddAutoIncrementalPK(this GridView gridView, string ColumnName)
        {
            DataTable dt = gridView.DataTable();
            dt.AddAutoIncrementalColumn(ColumnName);
            dt.SetPK(ColumnName);
            gridView.GetManager().PK = ColumnName;
            gridView.MakeColumnsReadOnly(ColumnName);
        }
        #endregion

        #region Serialize
        public static string Serialize(this GridView gridView)
        {
            gridView.EndEditing();
            return gridView.DataTable().Serialize();
        }

        public static string SerializeChanges(this GridView gridView)
        {
            gridView.EndEditing();
            return gridView.DataTable().SerializeChanges();
        }
        #endregion

        #region Update
        public static DataTable Update(this GridView gridView, string ColumnNames = "", string SourceSqlTableName = "")
        {
            gridView.EndEditing();

            DataTable dtGrid = gridView.DataTable();
            Dictionary<string, string> expressions = new Dictionary<string, string>();
            List<string> columnNames = new List<string>();

            foreach (DataColumn col in dtGrid.Columns)
            {
                if (col.Expression != string.Empty)
                {
                    expressions.Add(col.ColumnName, col.Expression);
                    col.Expression = "";
                }
                else
                    columnNames.Add(col.ColumnName);
            }

            if (SourceSqlTableName == "")
            {
                columnNames.Sort();
                string result = string.Join(",", columnNames.ToArray());
                DataTable tables = Session.DataManager.ExecuteDataTable("GetTableByColumns", result);
                if (tables.Rows.Count == 0)
                    throw new ApplicationException("Sütunlardan tablo ismi belirlenemedi. Update komutunda tablo ismi belirtin.");
                if (tables.Rows.Count > 1)
                    throw new ApplicationException("Veritabanında aynı sütunları içeren birden fazla tablo var. Update komutunda tablo ismi belirtin.");
                else
                    SourceSqlTableName = tables.Rows[0][0].ToString();
            }

            string colNames = string.Empty;

            if (ColumnNames == "")
                colNames = Session.DataManager.ExecuteDataTable("GetColumnsByTable", SourceSqlTableName).Rows[0][0].ToStr();
            else
                colNames = ColumnNames;

            SqlDataAdapter da = new SqlDataAdapter(string.Format("SELECT {0} FROM {1}", colNames, SourceSqlTableName), Session.DataManager.ConnectionString);
            SqlCommandBuilder builder = new SqlCommandBuilder(da);
            builder.QuotePrefix = "[";
            builder.QuoteSuffix = "]";
            builder.ConflictOption = ConflictOption.OverwriteChanges;
            builder.SetAllValues = false;

            da.UpdateCommand = builder.GetUpdateCommand(true);
            da.InsertCommand = builder.GetInsertCommand(true);
            da.DeleteCommand = builder.GetDeleteCommand(true);

            DataTable dtChanges = dtGrid.GetChanges();

            foreach (KeyValuePair<string, string> keys in expressions)
                dtGrid.Columns[keys.Key].Expression = keys.Value;

            da.RowUpdated += update_RowUpdated;
            da.RowUpdating += update_RowUpdating;

            if (dtChanges != null && dtChanges.Rows.Count > 0)
            {
                dtChanges.Columns.Add("NewId", typeof(int));
                da.Update(dtChanges);

                foreach (DataRow drChange in dtChanges.Select("NewId is not null"))
                {
                    string pk = gridView.GetManager().PK;
                    if (pk == "")
                        throw new ApplicationException("Otomatik update yapısında yeni eklenen satırlar varsa PK belirtilmeli");

                    int oldId = drChange[pk].ToInt();
                    int newId = drChange["NewId"].ToInt();

                    dtGrid.Select(pk + "=" + oldId)[0][pk] = newId;
                }

                dtGrid.AcceptChanges();
                return dtChanges;
            }
            else
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("NewId", typeof(int));
                return dt;
            }
        }

        public static void UpdateAll(this GridView gvMaster, string MasterColumnNames = "", string MasterSQLTable = "", string DetailColumnNames = "", string DetailSQLTable = "")
        {
            GridManager gmMaster = gvMaster.GetManager();
            if (gmMaster.DetailGrids.Count != 1)
                throw new ApplicationException("Hiyerarşik update için TEK BİR detail tanımlanmalı");
            if (gmMaster.PK == "")
                throw new ApplicationException("Hiyerarşik update için detail grid TEK BİR PK üzerinden bağlanmalı");

            GridView gvDetail = gmMaster.DetailGrids[0];

            gvMaster.EndEditing();
            gvDetail.EndEditing();  //bu olmayınca hiyerarşik update'te DevEx inner exception'ları geliyor.

            gvMaster.Update(MasterColumnNames, MasterSQLTable);
            gvDetail.Update(DetailColumnNames, DetailSQLTable);
        }

        private static void update_RowUpdating(object sender, SqlRowUpdatingEventArgs e)
        {
            if (e.StatementType == StatementType.Insert)
            {
                e.Command.Parameters.Add("@id", SqlDbType.Int);
                e.Command.Parameters["@id"].Direction = ParameterDirection.Output;
                e.Command.CommandText += ";SET @id = SCOPE_IDENTITY();";
            }
        }

        private static void update_RowUpdated(object sender, SqlRowUpdatedEventArgs e)
        {
            if (e.StatementType == StatementType.Insert)
                e.Row["NewId"] = e.Command.Parameters["@id"].Value;
        }
        #endregion
    }
}